<template>
    <el-container>
        <el-aside
            v-show="!editTestStepActivate"
            style="width: 250px; margin-top:10px;"
        >
            <div class="nav-api-side">
                <div class="api-tree">
                    <el-input
                        placeholder="请输入关键字进行过滤"
                        v-model="filterText"
                        size="medium"
                        clearable
                        prefix-icon="el-icon-search"
                    ></el-input>

                    <el-tree
                        @node-click="handleNodeClick"
                        :data="dataTree"
                        node-key="id"
                        :default-expand-all="false"
                        :expand-on-click-node="false"
                        highlight-current
                        :filter-node-method="filterNode"
                        ref="tree2"
                    >
                        <span
                            class="custom-tree-node"
                            slot-scope="{ node, data }"
                        >
                            <span class="custom-tree-node-span">
                                <i
                                    v-if="node.childNodes.length > 0"
                                    class="el-icon-folder-opened"
                                ></i>
                                <i v-else class="el-icon-folder"></i
                                >&nbsp;&nbsp;{{ node.label }}
                            </span>

                            <span style="flex-shrink: 0; margin-left: 5px;">
                                <el-badge
                                    :value="data.data_count"
                                    :max="99"
                                    type="primary"
                                ></el-badge>
                            </span>
                        </span>
                    </el-tree>
                </div>
            </div>
        </el-aside>
        <el-container class="loading-container">
            <el-main v-loading="loading" style="padding: 20px 20px 0px 20px;">
                <div
                    class="recordapi__header"
                    v-show="!editTestStepActivate"
                    style="margin-top: -10px; margin-left: -10px"
                >
                    <div class="recordapi__header" :style="{ flex: 1 }">
                        <div class="recordapi__header--item">
                            <el-input
                                clearable
                                size="medium"
                                placeholder="请输入接口名称"
                                style="width: 300px"
                                @input="inputVal"
                                :value="search"
                                @keyup.enter.native="getAPIList"
                            ></el-input>
                        </div>
                        <div class="recordapi__header--item">
                            <el-button
                                plain
                                size="medium"
                                icon="el-icon-refresh"
                                @click="resetSearch"
                                >重置</el-button
                            >
                        </div>
                        <div class="recordapi__header--item">
                            <el-dropdown @command="tagChangeHandle">
                                <el-button type="primary" size="medium">
                                    状态
                                    <i
                                        class="el-icon-arrow-down el-icon--right"
                                    ></i>
                                </el-button>
                                <el-dropdown-menu slot="dropdown">
                                    <el-dropdown-item command="1"
                                        >成功</el-dropdown-item
                                    >
                                    <el-dropdown-item command="0"
                                        >未知</el-dropdown-item
                                    >
                                    <el-dropdown-item command="2"
                                        >失败</el-dropdown-item
                                    >
                                    <el-dropdown-item command=""
                                        >所有</el-dropdown-item
                                    >
                                </el-dropdown-menu>
                            </el-dropdown>
                        </div>
                        <div class="recordapi__header--item">
                            <el-select
                                size="medium"
                                v-model="selectUser"
                                placeholder="创建人"
                                filterable
                                :style="{ width: '120px' }"
                            >
                                <el-option
                                    v-for="(item, index) in users"
                                    :key="index"
                                    :label="item.label"
                                    :value="item.value"
                                ></el-option>
                            </el-select>
                        </div>
                    </div>

                    <div class="recordapi__header" :style="{ flex: 1 }">
                        <div class="recordapi__header--item">
                            <el-input
                                size="medium"
                                style="width: 500px"
                                placeholder="请输入测试用例名称"
                                v-model="testName"
                                clearable
                                v-if="testData.length > 0"
                            >
                                <el-select
                                    size="medium"
                                    v-model="testTag"
                                    slot="prepend"
                                    placeholder="请选择"
                                    style="width: 105px"
                                >
                                    <el-option
                                        v-for="value in tagOptions"
                                        :key="value"
                                        :label="value"
                                        :value="value"
                                    ></el-option>
                                </el-select>
                            </el-input>
                        </div>
                        <el-button
                            size="medium"
                            style="margin-left: 10px"
                            v-if="testData.length > 0"
                            type="primary"
                            :loading="loading"
                            @click="handleClickRun"
                            >发送</el-button
                        >

                        <div class="recordapi__header--item">
                            <el-button
                                size="medium"
                                v-if="testData.length > 0"
                                slot="append"
                                type="primary"
                                @click="handleClickSave"
                                :title="
                                    disabledSave
                                        ? '不能修改其他人的用例'
                                        : '保存用例'
                                "
                                :disabled="disabledSave"
                                >保存</el-button
                            >
                        </div>
                    </div>
                </div>

                <div
                    v-show="!editTestStepActivate"
                    style="position: relative; height: 675px; margin-top: 10px;"
                >
                    <div
                        style="height: calc(100% - 50px); overflow-y: auto; overflow-x: hidden;"
                    >
                        <el-row :gutter="20">
                            <el-col :span="12">
                                <div
                                    v-for="(item, index) in apiData.results"
                                    draggable="true"
                                    @dragstart="
                                        currentAPI = JSON.parse(
                                            JSON.stringify(item)
                                        )
                                    "
                                    style="cursor: pointer; margin-top: 10px; overflow: auto"
                                    :key="index"
                                >
                                    <div
                                        class="block"
                                        :class="
                                            `block_${item.method.toLowerCase()}`
                                        "
                                    >
                                        <span
                                            class="block-method block_method_color"
                                            :class="
                                                `block_method_${item.method.toLowerCase()}`
                                            "
                                            >{{
                                                item.method.toUpperCase()
                                            }}</span
                                        >
                                        <div class="block">
                                            <span
                                                class="block-method block_method_color block_method_options"
                                                v-if="item.creator === 'yapi'"
                                                :title="'从YAPI导入的接口'"
                                                >YAPI</span
                                            >
                                        </div>
                                        <span
                                            class="block-method block-api-name-url"
                                            >{{ item.url }}</span
                                        >
                                        <span class="block-api-name-url">{{
                                            item.name
                                        }}</span>
                                        <div>
                                            <span
                                                class="el-icon-s-flag"
                                                v-if="item.cases.length > 0"
                                                :title="
                                                    '接口已被用例引用' +
                                                        item.cases.length +
                                                        '次'
                                                "
                                            ></span>
                                        </div>
                                    </div>
                                </div>
                            </el-col>
                            <el-col :span="12" class="el-col">
                                <el-dialog
                                    v-if="dialogTableVisible"
                                    :visible.sync="dialogTableVisible"
                                    width="70%"
                                >
                                    <report :summary="summary"></report>
                                </el-dialog>

                                <div
                                    @drop="drop($event)"
                                    @dragover="allowDrop($event)"
                                    class="drag-drop-zone"
                                >
                                    <div>
                                        <span
                                            v-if="testData.length === 0"
                                            style="color: red"
                                            >温馨提示：
                                            <br />从左边拖拽API至此区域组成业务用例<br />上下拖动此区域API调整API调用顺序
                                        </span>
                                        <div
                                            v-if="isConfigExist"
                                            class="block block_test"
                                            @mousemove="currentTest = -1"
                                        >
                                            <span
                                                class="block-method block_method_config block_method_color"
                                                >{{
                                                    testData[0].body.method
                                                }}</span
                                            >
                                            <input
                                                class="block-test-name"
                                                v-model="testData[0].body.name"
                                                disabled
                                            />
                                            <el-button
                                                style="position: absolute; right:12px; top:8px"
                                                v-show="currentTest === -1"
                                                type="danger"
                                                icon="el-icon-delete"
                                                title="删除"
                                                circle
                                                size="mini"
                                                @click="testData.splice(0, 1)"
                                            ></el-button>
                                        </div>
                                        <draggable
                                            v-model="testData"
                                            @end="dragEnd"
                                            @start="length = testData.length"
                                            :animation="200"
                                        >
                                            <div
                                                v-for="(test,
                                                index) in testData"
                                                :key="index"
                                                class="block block_test"
                                                @mousemove="currentTest = index"
                                                v-if="
                                                    test.body.method !==
                                                        'config'
                                                "
                                            >
                                                <span
                                                    class="block-method block_method_test block_method_color"
                                                    >Step_{{ index }}</span
                                                >
                                                <input
                                                    class="block-test-name"
                                                    v-model="test.body.name"
                                                />
                                                <el-button
                                                    style="position: absolute; right: 156px; top: 8px"
                                                    v-show="
                                                        currentTest === index
                                                    "
                                                    type="info"
                                                    icon="el-icon-edit"
                                                    title="编辑"
                                                    circle
                                                    size="mini"
                                                    @click="
                                                        editTestStepActivateHandle
                                                    "
                                                ></el-button>
                                                <el-button
                                                    style="position: absolute; right: 120px; top: 8px"
                                                    v-show="
                                                        currentTest === index
                                                    "
                                                    type="danger"
                                                    icon="el-icon-document-copy"
                                                    title="复制当前步骤"
                                                    circle
                                                    size="mini"
                                                    @click="
                                                        handleCopyStep(index)
                                                    "
                                                ></el-button>
                                                <el-button
                                                    style="position: absolute; right: 84px; top: 8px"
                                                    v-show="
                                                        currentTest === index
                                                    "
                                                    type="success"
                                                    icon="el-icon-caret-right"
                                                    title="单个运行"
                                                    circle
                                                    size="mini"
                                                    @click="handleSingleRun"
                                                ></el-button>
                                                <el-button
                                                    style="position: absolute; right: 48px; top: 8px"
                                                    v-show="
                                                        currentTest === index
                                                    "
                                                    type="primary"
                                                    icon="el-icon-caret-right"
                                                    title="运行开始到当前为止的所有api"
                                                    circle
                                                    size="mini"
                                                    @click="
                                                        handlePartialRun(index)
                                                    "
                                                ></el-button>
                                                <el-button
                                                    circle
                                                    style="position: absolute; right: 12px; top: 8px"
                                                    v-show="
                                                        currentTest === index
                                                    "
                                                    type="danger"
                                                    icon="el-icon-delete"
                                                    title="删除"
                                                    size="mini"
                                                    @click="
                                                        handleSingleDel(index)
                                                    "
                                                ></el-button>
                                            </div>
                                        </draggable>
                                    </div>
                                </div>
                            </el-col>
                        </el-row>
                    </div>
                    <div class="pagination-container">
                        <el-pagination
                            v-show="apiData.count !== 0"
                            background
                            @current-change="handlePageChange"
                            @size-change="handleSizeChange"
                            :current-page.sync="currentPage"
                            :page-sizes="[10, 15, 20]"
                            :page-size="pageSize"
                            :pager-count="5"
                            layout="total, sizes, prev, pager, next, jumper"
                            :total="apiData.count"
                            style="margin-top: 5px"
                        ></el-pagination>
                    </div>
                </div>
                <test-body
                    v-if="editTestStepActivate"
                    :response="testData[currentTest]"
                    :config="config"
                    :disabledSave="disabledSave"
                    @escEdit="escEditHandle"
                    @getNewBody="handleNewBody"
                ></test-body>
            </el-main>
            <el-button
                v-if="showCancel"
                @click="cancelRequest"
                class="custom-button"
                size="mini"
                >取消</el-button
            >
        </el-container>
    </el-container>
</template>

<script>
import draggable from "vuedraggable";
import TestBody from "./TestBody";
import Report from "@/pages/reports/DebugReport";
import axios from "axios";
import { isEqual } from "lodash";

export default {
    name: "EditTest",
    components: {
        draggable,
        TestBody,
        Report
    },
    props: {
        config: {
            required: true
        },
        project: {
            required: true
        },
        node: {
            required: true
        },
        testStepResp: {
            required: false
        },
        editBack: Boolean,
        resetEditTestStepActivate: Boolean,
        rigEnv: [String, Number],
        tag: [String, Number],
        search: [String, Number],
        addTestActivate: {
            type: Boolean,
            required: true
        }
    },
    data() {
        return {
            originalData: [],
            tagOptions: {
                1: "冒烟用例",
                2: "集成用例",
                3: "监控用例",
                4: "核心用例"
            },
            isSuperuser: this.$store.state.is_superuser,
            userId: this.$store.state.id,
            disabledSave: true,
            showCancel: false,
            loading: false,
            dialogTableVisible: false,
            editTestStepActivate: false,
            currentPage: 1,
            pageSize: 10,
            length: 0,
            testId: "",
            testName: "",
            relation: "",
            testTag: "集成用例",
            currentTest: "",
            currentNode: "",
            currentAPI: "",
            data: "",
            filterText: "",
            expand: "&#xe65f;",
            dataTree: [],
            summary: {},
            apiData: {
                count: 0,
                results: []
            },
            testData: [],
            selectUser: this.$store.state.name,
            users: [],
            searchDebounce: null
        };
    },
    computed: {
        isConfigExist: {
            get() {
                return (
                    this.testData.length > 0 &&
                    this.testData[0].body.method === "config" &&
                    this.testData[0].body.name !== "请选择"
                );
            }
        }
    },
    watch: {
        search() {
            this.debouncedGetAPIList();
        },
        selectUser() {
            this.debouncedGetAPIList();
        },
        config() {
            const temp = { body: { name: this.config, method: "config" } };
            if (
                (this.testData.length === 0 ||
                    this.testData[0].body.method !== "config") &&
                this.config !== "请选择"
            ) {
                this.testData.splice(0, 0, temp);
            } else {
                if (this.config !== "请选择") {
                    this.testData.splice(0, 1, temp);
                }
            }
        },
        editBack() {
            this.handleResetStatus();
            if (this.editBack) {
                this.testId = "";
                this.testName = "";
                this.testData = [];
            }
            this.editTestStepActivate = false;
        },
        resetEditTestStepActivate() {
            this.editTestStepActivate = false;
        },
        filterText(val) {
            this.$refs.tree.filter(val);
        },
        testStepResp: {
            deep: true,
            handler() {
                this.handleSavePermission();
                try {
                    this.testName = this.testStepResp.case.name;
                    this.testId = this.testStepResp.case.id;
                    this.testTag = this.testStepResp.case.tag;
                    this.relation = this.testStepResp.case.relation;
                    this.testData = JSON.parse(
                        JSON.stringify(this.testStepResp.step)
                    );
                } catch (e) {
                    this.testName = "";
                    this.testId = "";
                    this.testTag = "集成用例";
                    this.testData = [];
                }
                this.setOriginalData();
            }
        },
        testName() {
            this.checkForChanges();
        },
        testTag() {
            this.checkForChanges();
        },
        testData: {
            deep: true,
            handler() {
                this.checkForChanges();
            }
        }
    },
    methods: {
        escEditHandle() {
            this.editTestStepActivate = false;
            this.$emit("showListBtn", true);
        },
        editTestStepActivateHandle() {
            this.editTestStepActivate = true;
            this.$emit("showListBtn", false);
        },
        checkForChanges() {
            const currentData = {
                testName: this.testName,
                testTag: this.testTag,
                testSteps: this.testData
            };
            const hasChanged = !isEqual(this.originalData, currentData);
            this.$emit("dataChanged", hasChanged);
        },
        setOriginalData() {
            if (this.testStepResp && this.testStepResp.step) {
                this.originalData = {
                    testName: this.testStepResp.case.name,
                    testTag: this.testStepResp.case.tag,
                    testSteps: JSON.parse(
                        JSON.stringify(this.testStepResp.step)
                    )
                };
            } else {
                this.originalData = {
                    testName: this.testName,
                    testTag: this.testTag,
                    testSteps: JSON.parse(JSON.stringify(this.testData))
                };
            }
        },
        debouncedGetAPIList() {
            clearTimeout(this.searchDebounce);
            this.searchDebounce = setTimeout(() => {
                this.currentPage = 1;
                this.getAPIList();
            }, 300);
        },
        handleSavePermission() {
            // 新增用例时，所有人都能保存
            if (this.addTestActivate === false) {
                this.disabledSave = false;
            }
            // 用例创建人和超级管理员可以编辑并保存用例, 其他人只能打开用例，无法保存
            if (this.testStepResp && this.testStepResp.case) {
                this.disabledSave = !(
                    this.isSuperuser ||
                    this.testStepResp.case.creator === this.userId
                );
            }
        },
        inputVal(val) {
            this.$emit("update:search", val);
        },
        handleNewBody(body, newBody) {
            this.editTestStepActivate = false;
            const source_api_id = this.testData[this.currentTest].source_api_id;
            const step = this.testData[this.currentTest].case;
            const id = this.testData[this.currentTest].id;
            this.testData[this.currentTest] = {
                body: body,
                newBody: newBody,
                case: step,
                id: id,
                source_api_id: source_api_id
            };
            // 编辑用例步骤内容时，也调用接口保存
            this.handleClickSave(false, true);
        },
        rigEnvChangeHandle(command) {
            this.$emit("update:rigEnv", command);
            this.getAPIList();
        },
        handleClickSave(addTestFinish = true, isEditTestStep = false) {
            if (this.validateData()) {
                if (this.testId === "") {
                    this.addTestSuite(addTestFinish, isEditTestStep);
                } else {
                    this.updateTestSuite(addTestFinish, false, isEditTestStep);
                }
            }
        },
        cancelToken() {
            this.showCancel = true;

            // 创建 cancel token
            this.cancelTokenSource = axios.CancelToken.source();

            // 设置一个定时器，2分钟后执行
            return setTimeout(() => {
                this.apiRunning = false;
                this.cancelTokenSource.cancel("Request timed out");
            }, 120000);
        },
        cancelRequest() {
            this.loading = false; // 关闭Loading
            this.showCancel = false; // 隐藏‘取消请求’按钮
            this.cancelTokenSource.cancel("User cancelled the request"); // 取消请求
        },
        // 全部运行
        handleClickRun() {
            if (this.validateData()) {
                this.loading = true;
                const timeout = this.cancelToken();
                this.$api
                    .runSingleTestSuite(
                        {
                            name: this.testName,
                            body: this.testData,
                            project: this.project
                        },
                        this.cancelTokenSource.token
                    )
                    .then(resp => {
                        clearTimeout(timeout); // 清除定时器
                        this.loading = false;
                        this.summary = resp;
                        this.dialogTableVisible = true;
                        this.showCancel = false; // 请求成功完成，隐藏‘取消请求’按钮
                    })
                    .catch(err => {
                        clearTimeout(timeout); // 清除定时器
                        if (!axios.isCancel(err)) {
                            // 如果错误不是由取消请求引起的，则处理错误
                            this.loading = false;
                            this.$message.error(err);
                        }
                        this.showCancel = false; // 请求失败，隐藏‘取消请求’按钮
                    });
            }
        },
        // 运行开始到当前位置的所有api
        handlePartialRun(index) {
            if (this.validateData()) {
                this.loading = true;
                const timeout = this.cancelToken();
                this.$api
                    .runSingleTestSuite(
                        {
                            name: this.testName,
                            body: this.testData.slice(0, index + 1),
                            project: this.project
                        },
                        this.cancelTokenSource.token
                    )
                    .then(resp => {
                        clearTimeout(timeout); // 清除定时器
                        this.loading = false;
                        this.summary = resp;
                        this.dialogTableVisible = true;
                        this.showCancel = false;
                    })
                    .catch(err => {
                        clearTimeout(timeout);
                        if (!axios.isCancel(err)) {
                            // 如果错误不是由取消请求引起的，则处理错误
                            this.loading = false;
                            this.$message.error(err);
                        }
                        this.showCancel = false;
                    });
            }
        },
        // 单个运行
        handleSingleRun() {
            let config = null;
            this.loading = true;
            const timeout = this.cancelToken();
            if (
                this.testData.length > 0 &&
                this.testData[0].body.method === "config" &&
                this.testData[0].body.name !== "请选择"
            ) {
                config = this.testData[0].body;
            } else {
                this.$notify.warning({
                    title: "提示",
                    message: "测试用例必须包含配置",
                    duration: this.$store.state.duration
                });
                this.loading = false;
                return;
            }
            this.$api
                .runSingleTest(
                    {
                        config: config,
                        body: this.testData[this.currentTest],
                        project: this.project
                    },
                    this.cancelTokenSource.token
                )
                .then(resp => {
                    clearTimeout(timeout); // 清除定时器
                    this.loading = false;
                    this.summary = resp;
                    this.dialogTableVisible = true;
                    this.showCancel = false;
                })
                .catch(err => {
                    clearTimeout(timeout);
                    if (!axios.isCancel(err)) {
                        // 如果错误不是由取消请求引起的，则处理错误
                        this.loading = false;
                        this.$message.error(err);
                    }
                    this.showCancel = false;
                });
        },
        failure(resp) {
            this.$notify.error({
                title: "失败",
                message: resp["msg"],
                duration: this.$store.state.duration
            });
        },
        handleSingleDel(index) {
            this.testData.splice(index, 1);
            if (
                this.testData.length === 1 &&
                this.testData[0].body.name === "请选择"
            ) {
                this.testData.splice(0, 1);
            }
        },
        handlePageChange() {
            this.$api
                .getAPIPaginationByPage({
                    params: {
                        page: this.currentPage,
                        size: this.pageSize,
                        node: this.currentNode,
                        project: this.project,
                        tag: this.tag,
                        rigEnv: this.rigEnv,
                        search: this.search
                    }
                })
                .then(resp => {
                    this.apiData = resp.data;
                });
        },
        handleSizeChange(newSize) {
            this.pageSize = newSize;
            // 计算新的最大页码
            let maxPage = Math.ceil(this.apiData.count / newSize);
            if (this.currentPage > maxPage) {
                // 如果当前页码超出了范围，请将其设置为最大页面
                this.currentPage = maxPage;
            }
            this.$api
                .getAPIPaginationByPage({
                    params: {
                        page: this.currentPage,
                        size: newSize,
                        node: this.currentNode,
                        project: this.project,
                        tag: this.tag,
                        rigEnv: this.rigEnv,
                        search: this.search
                    }
                })
                .then(resp => {
                    this.apiData = resp.data;
                });
        },
        // 接口状态搜索
        tagChangeHandle(command) {
            this.$emit("update:tag", command);
            this.$nextTick(() => {
                this.$api
                    .apiList({
                        params: {
                            page: this.currentPage,
                            size: this.pageSize,
                            node: this.currentNode,
                            project: this.project,
                            tag: this.tag,
                            rigEnv: this.rigEnv,
                            search: this.search,
                            creator: this.selectUser
                        }
                    })
                    .then(resp => {
                        if (resp.success) {
                            this.apiData = resp.data;
                        } else {
                            this.$message({
                                type: "error",
                                message: resp.msg
                            });
                        }
                    });
            });
        },
        handleResetStatus() {
            this.currentPage = 1;
            this.pageSize = 10;
            this.selectUser = this.$store.state.name;
            this.currentNode = "";
            this.$emit("update:search", "");
            this.$emit("update:tag", "");
            this.$emit("update:rigEnv", "");
        },
        resetSearch() {
            this.handleResetStatus();
            this.getAPIList();
        },
        getAPITree() {
            this.$api
                .getTree(this.$route.params.id, {
                    params: {
                        type: 1
                    }
                })
                .then(resp => {
                    this.dataTree = resp["tree"];
                });
        },
        handleNodeClick(node, data) {
            // 点击子目录把页码重置设置为1
            this.currentPage = 1;
            this.currentNode = node.id;
            this.data = data;
            this.getAPIList();
        },
        filterNode(value, data) {
            if (!value) return true;
            return data.label.indexOf(value) !== -1;
        },
        dragEnd() {
            if (this.testData.length > this.length) {
                this.testData.splice(this.length, 1);
            }
        },
        drop(event) {
            event.preventDefault();
            // 创建用例时, 默认加上config
            if (this.testData.length === 0) {
                this.testData.push({
                    body: { name: this.config, method: "config" }
                });
            }
            if (this.currentAPI) {
                this.testData.push(this.currentAPI);
                this.currentAPI = "";
            }
        },
        allowDrop(event) {
            event.preventDefault();
        },
        getUserList() {
            this.$api.getUserList().then(resp => {
                for (let i = 0; i < resp.length; i++) {
                    this.users.push({
                        label: resp[i].name,
                        value: resp[i].name
                    });
                }
                // 在数组第一个位置插入值
                this.users.unshift({ label: "所有人", value: "" });
            });
        },
        validateData() {
            if (this.testName === "" || this.testName.length > 100) {
                this.$notify.warning({
                    title: "提示",
                    message: "用例名称必填, 不能超过100个字符",
                    duration: this.$store.state.duration
                });
                return false;
            }

            if (this.testData.length === 0) {
                this.$notify.warning({
                    title: "提示",
                    message: "测试用例至少包含一个接口",
                    duration: this.$store.state.duration
                });
                return false;
            }

            if (
                this.testData[0].body.method === "config" &&
                this.testData.length === 1
            ) {
                this.$notify.warning({
                    title: "提示",
                    message: "测试用例至少包含一个接口",
                    duration: this.$store.state.duration
                });
                return false;
            }

            if (
                this.testData[0].body.name === "请选择" ||
                this.testData[0].body.method !== "config"
            ) {
                this.$notify.warning({
                    title: "提示",
                    message: "测试用例必须包含配置",
                    duration: this.$store.state.duration
                });
                return false;
            }
            return true;
        },
        addTestSuite(addTestFinish, isEditTestStep) {
            let len = this.testData.length;
            if (this.testData[0].body.method === "config") {
                len -= 1;
            }
            this.$api
                .addTestCase({
                    length: len,
                    project: this.project,
                    relation: this.node,
                    name: this.testName,
                    body: this.testData,
                    tag: this.testTag
                })
                .then(resp => {
                    if (resp.success) {
                        this.testId = resp.test_id;

                        if (addTestFinish) {
                            this.$emit("addSuccess");
                        }

                        if (isEditTestStep) {
                            this.$emit("showListBtn", true);
                        } else {
                            this.handleResetStatus(); // 重置搜索条件
                            this.$emit("showListBtn", false);
                        }
                        this.$message.success(resp.msg);
                    } else {
                        this.$message.error(resp.msg);
                    }
                });
        },
        updateTestSuite(addTestFinish, refresh = false, isEditTestStep) {
            let len = this.testData.length;
            if (this.testData[0].body.method === "config") {
                len -= 1;
            }

            this.$api
                .updateTestCase(this.testId, {
                    length: len,
                    name: this.testName,
                    tag: this.testTag,
                    body: this.testData,
                    project: this.project
                })
                .then(resp => {
                    // 刷新用例步骤
                    // 注意需要等到用例步骤刷新完毕后，再刷新用例列表
                    if (refresh) {
                        this.refreshStep();
                    }

                    if (resp.success) {
                        if (addTestFinish) {
                            this.$emit("addSuccess");
                        }

                        if (isEditTestStep) {
                            this.$emit("showListBtn", true);
                        } else {
                            this.handleResetStatus(); // 重置搜索条件
                            this.$emit("showListBtn", false);
                        }
                        this.$message.success(resp.msg);
                    } else {
                        this.$message.error(resp.msg);
                    }
                });
        },
        refreshStep() {
            this.$api.editTest(this.testId).then(resp => {
                this.testData = JSON.parse(JSON.stringify(resp.step));
            });
        },
        getAPIList() {
            this.$nextTick(() => {
                this.$api
                    .apiList({
                        params: {
                            page: this.currentPage,
                            size: this.pageSize,
                            node: this.currentNode,
                            project: this.project,
                            search: this.search,
                            rigEnv: this.rigEnv,
                            tag: this.tag,
                            creator: this.selectUser
                        }
                    })
                    .then(resp => {
                        if (resp.success) {
                            this.apiData = resp.data;
                        } else {
                            this.$message({
                                type: "error",
                                message: resp.msg
                            });
                        }
                    });
            });
        },
        handleCopyStep(index) {
            let copyStepObj = JSON.parse(JSON.stringify(this.testData[index]));
            copyStepObj.is_copy = true;
            this.testData.splice(index + 1, 0, copyStepObj);
            this.updateTestSuite(false, true);
        }
    },
    mounted() {
        this.getAPITree();
        this.getAPIList();
        this.getUserList();
        this.setOriginalData();
    }
};
</script>

<style scoped>
.el-col {
    min-height: 1px;
}

.test-list {
    height: 750px;
}

.block_test {
    margin-top: 10px;
    border: 1px solid #49cc90;
    background-color: rgba(236, 248, 238, 0.4);
}

.block_method_test {
    background-color: darkcyan;
}

.block_method_config {
    background-color: red;
}

.block-test-name {
    /*修改用例中API名字显示不全*/
    width: 450px;
    /*超过宽度自动变成...*/
    text-overflow: ellipsis;
    overflow: hidden;
    white-space: nowrap;
    padding-left: 10px;
    font-family: Open Sans, sans-serif;
    color: #3b4151;
    border: none;
    outline: none;
    background: rgba(236, 248, 238, 0.4);
}

.recordapi__header {
    display: flex;
    align-items: center;
}

.recordapi__header--item {
    display: flex;
    margin-left: 10px;
}

.custom-button {
    position: absolute; /* 使用绝对定位 */
    top: calc(50% + 40px); /* 从容器的顶部开始，向下移动50% + 20px */
    left: 50%; /* 从容器的左边开始，向右移动50% */
    transform: translate(-50%, -50%); /* 使用 transform 居中按钮 */
    z-index: 2000; /* 确保按钮在 Loading 动画之上 */
}

.loading-container {
    position: relative; /* 添加这个让子元素可以相对于此容器定位 */
}

.pagination-container {
    display: flex;
    justify-content: left;
    align-items: center;
    position: absolute;
    bottom: 0;
    left: 0;
    right: 0;
}

.drag-drop-zone {
    min-height: 600px;
}
</style>
